package com.zhou.essearch.service.impl;

import com.zhou.essearch.document.ProductDocument;
import com.zhou.essearch.page.Page;
import com.zhou.essearch.service.BaseSearchService;
import org.elasticsearch.common.text.Text;
import org.elasticsearch.index.query.*;
import org.springframework.data.elasticsearch.core.SearchHit;
import org.springframework.data.elasticsearch.core.SearchHits;
import org.elasticsearch.search.fetch.subphase.highlight.HighlightBuilder;
import org.elasticsearch.search.sort.FieldSortBuilder;
import org.elasticsearch.search.sort.SortOrder;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.data.domain.PageRequest;
import org.springframework.data.domain.Pageable;
import org.springframework.data.elasticsearch.core.ElasticsearchRestTemplate;
import org.springframework.data.elasticsearch.core.mapping.IndexCoordinates;
import org.springframework.data.elasticsearch.core.query.NativeSearchQuery;
import org.springframework.data.elasticsearch.core.query.NativeSearchQueryBuilder;
import org.springframework.stereotype.Service;

import javax.annotation.Resource;
import java.util.*;

/**
 * elasticsearch 搜索引擎
 * @author wanghaoran
 * @version 0.1
 * @date 2021/12/13 15:33
 */
@Service
public class BaseSearchServiceImpl<T> implements BaseSearchService<T> {
    private Logger log = LoggerFactory.getLogger(getClass());
    @Resource
    private ElasticsearchRestTemplate elasticsearchRestTemplate;

//    @Override
//    public List<T> query(String keyword, Class<T> clazz) {
//        SearchQuery searchQuery = new NativeSearchQueryBuilder()
//                .withQuery(new QueryStringQueryBuilder(keyword))
//                .withSort(SortBuilders.scoreSort().order(SortOrder.DESC))
//                // .withSort(new FieldSortBuilder("createTime").order(SortOrder.DESC))
//                .build();
//
//        return elasticsearchRestTemplate.queryForList(searchQuery,clazz);
//    }

    /**
     * 高亮显示
     * @auther: wanghaoran
     * @date: 2022/01/13 21:22
     */
    @Override
    public  List  queryHit(String keyword,String indexName,String ... fieldNames) {
        //条件
        MatchAllQueryBuilder queryBuilder = QueryBuilders.matchAllQuery();
        //排序
        FieldSortBuilder sortBuilder = new FieldSortBuilder("id").order(SortOrder.ASC);
        //分页
        Pageable pageable = PageRequest.of(0, 1000);
        // 设置高亮,使用默认的highlighter高亮器
        HighlightBuilder highlightBuilder = createHighlightBuilder(fieldNames);
        QueryBuilder filter=new QueryStringQueryBuilder(keyword);
        //搜索
        NativeSearchQuery query = new NativeSearchQueryBuilder().withQuery(queryBuilder).withFilter(filter).withPageable(pageable).withHighlightBuilder(highlightBuilder).build();
        org.springframework.data.elasticsearch.core.SearchHits<ProductDocument> hits = elasticsearchRestTemplate.search(query, ProductDocument.class);

        return hits.toList();
    }
    /**
     * 高亮显示，返回分页 TODO还差高亮
     * @auther: wanghaoran
     * @date: 2022/01/18 10:29
     */
    @Override
    public Page<Map<String, Object>> queryHitByPage(int pageNo, int pageSize, String keyword, String indexName, String userId, Date startTime, Date endTime,String bustype,String searchField, String... fieldNames) {

        //条件
        BoolQueryBuilder boolQueryBuilder=QueryBuilders.boolQuery();
        QueryStringQueryBuilder queryBuilder = QueryBuilders.queryStringQuery(userId).field("userId");
        boolQueryBuilder.must(queryBuilder);
        if(startTime!=null&&endTime!=null){
            boolQueryBuilder.must(QueryBuilders.rangeQuery("fileCreateTime").from(startTime.getTime()).to(endTime.getTime()));
        }
        if(bustype!=null&&bustype.length()>0){
            boolQueryBuilder.must(QueryBuilders.queryStringQuery(bustype).field("bustype"));
        }
        if("title".equals(searchField)){
            boolQueryBuilder.must(QueryBuilders.queryStringQuery(keyword).field("title"));
        }else{
            boolQueryBuilder.must(QueryBuilders.queryStringQuery(keyword).field("content"));
        }

        //排序
        FieldSortBuilder sortBuilder = new FieldSortBuilder("fileId").order(SortOrder.DESC);
        //分页
        Pageable pageable = PageRequest.of(pageNo - 1, pageSize);
        // 设置高亮,使用默认的highlighter高亮器
        HighlightBuilder highlightBuilder = createHighlightBuilder(fieldNames);
        //搜索

        NativeSearchQuery query = new NativeSearchQueryBuilder().withQuery(boolQueryBuilder).withPageable(pageable).withHighlightBuilder(highlightBuilder).build();
        SearchHits<ProductDocument> hits = elasticsearchRestTemplate.search(query, ProductDocument.class);
        Long totalCount = hits.getTotalHits();
        Page<Map<String, Object>> page = new Page<>(pageNo,pageSize,totalCount.intValue());
        page.setList(hits.toList());
        // 取出高亮的结果数据，在该对象中
        // 遍历: 对返回的内容进行处理(高亮字段替换原来的字段)
        for(SearchHit<ProductDocument> searchHit:hits){
            // 获取searchHit中的高亮内容
            Map<String, List<String>> highlightFields = searchHit.getHighlightFields();
            // 将高亮的内容填充到content中
            searchHit.getContent().setTitle(highlightFields.get("title")==null ? searchHit.getContent().getTitle():highlightFields.get("title").get(0));
            searchHit.getContent().setContent(highlightFields.get("content")==null ? searchHit.getContent().getContent():highlightFields.get("content").get(0));
        }

        return page;
    }

    /**
     * 构造查询条件
     * @auther: wanghaoran
     * @date: 2022/01/18 10:42
     */
    private QueryBuilder createQueryBuilder(String keyword, String... fieldNames){
        // 构造查询条件,使用标准分词器.
        return QueryBuilders.multiMatchQuery(keyword,fieldNames)   // matchQuery(),单字段搜索
                .analyzer("ik_max_word")
                .operator(Operator.OR);
    }
    /**
     * 构造高亮器
     * @auther: wanghaoran
     * @date: 2022/01/18 10:44
     */
    private HighlightBuilder createHighlightBuilder(String... fieldNames){
        // 设置高亮,使用默认的highlighter高亮器
        HighlightBuilder highlightBuilder = new HighlightBuilder()
                // .field("productName")
                .preTags("<span style='color:red'>")
                .postTags("</span>");

        // 设置高亮字段
        for (String fieldName: fieldNames) highlightBuilder.field(fieldName);

        return highlightBuilder;
    }



    @Override
    public void deleteIndex(String indexName) {
        boolean delete = elasticsearchRestTemplate.indexOps(IndexCoordinates.of(indexName)).delete();
        System.out.println(delete);
    }
}
